package com.example.aigc_education.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.aigc_education.common.BusinessException;
import com.example.aigc_education.domain.DaysMatter;
import com.example.aigc_education.domain.vo.DaysMatterVO;
import com.example.aigc_education.mapper.DaysMatterMapper;
import com.example.aigc_education.service.DaysMatterService;
import com.example.aigc_education.service.converter.DaysMatterConverter;
import com.example.aigc_education.utils.SecurityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DaysMatterServiceImpl extends ServiceImpl<DaysMatterMapper, DaysMatter> implements DaysMatterService {

    @Resource
    private DaysMatterConverter daysMatterConverter;

    @Resource
    private DaysMatterMapper daysMatterMapper;
    /**
     * 添加倒数日事件
     *
     * @param daysMatter 倒数日
     * @return
     */
    @Override
    public DaysMatter addDaysMatter(DaysMatter daysMatter) {
        // 获取用户的id
         Long userId = SecurityUtils.getUserId();
        daysMatter.setUserId(userId);

        // 获取两个时间的间隔天数
        int daysBetween = getDaysNumByDay(daysMatter.getTargetDay(), daysMatter.getRepeatType());
        if(daysBetween >= 0){
            // 目标时间是未来
            daysMatter.setMatterType(2);
            daysMatter.setDaysNum(daysBetween);

        }else {
            // 目标时间是过去
            daysMatter.setMatterType(1);
            daysMatter.setDaysNum(Math.abs(daysBetween));

        }

        // 使用IService的save保存数据信息到数据库
        this.save(daysMatter);

        return daysMatter;
    }

    /**
     * 获取用户的所有的倒数日事件
     *
     * @return 倒数日事件的集合
     */
    @Override
    public List<DaysMatterVO> daysMatterList() {
        // 获取用户的id
        Long userId = SecurityUtils.getUserId();


        // 查询构造器
        LambdaQueryWrapper<DaysMatter> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DaysMatter::getUserId, userId);
        List<DaysMatter> list = this.list(queryWrapper);

        // 调整list集合里面的数据
        list.stream().map((item) -> {
            // 获取目标时间
            LocalDate targetDay = item.getTargetDay();
            // 间隔天数
            int daysBetween = getDaysNumByDay(targetDay, item.getRepeatType());
            if(daysBetween >= 0){
                // 目标时间是未来
                item.setMatterType(2);
                item.setDaysNum(daysBetween);

            }else {
                // 目标时间是过去
                item.setMatterType(1);
                item.setDaysNum(Math.abs(daysBetween));

            }

            // 状态——失效，只修改间隔天数
            if( item.getStatus() == 0){
                this.updateById(item);
                return item;
            }

            if(daysBetween == 0){
                int repeatNum = item.getRepeatNum();

                // 查看重复功能
                switch (item.getRepeatType()){
                    case 2:     // 按年重复
                        item.setTargetDay( item.getTargetDay().plusYears(repeatNum) );
                        break;
                    case 3:     // 按月重复
                        item.setTargetDay( item.getTargetDay().plusMonths(repeatNum) );
                        break;
                    case 4:     // 按周重复
                        item.setTargetDay( item.getTargetDay().plusWeeks(repeatNum) );
                        break;
                    case 5:     // 按天重复
                        item.setTargetDay( item.getTargetDay().plusDays(repeatNum) );
                        break;
                }

                int daysNum = getDaysNumByDay(item.getTargetDay(), item.getRepeatType());
                item.setDaysNum(daysNum);
            }

            this.updateById(item);
            return item;

        }).collect(Collectors.toList());

        // 按照状态降序，失效排在后面
        queryWrapper.orderByDesc(DaysMatter::getStatus);
        // 按照倒数日类型降序，未来的排在前面
        queryWrapper.orderByDesc(DaysMatter::getMatterType);
        // 按照距离目标事件的时间升序
        queryWrapper.orderByAsc(DaysMatter::getDaysNum);

        List<DaysMatterVO> daysMatterVOS = this.list(queryWrapper).stream().map((item) -> {
            DaysMatterVO daysMatterVO = daysMatterConverter.DaysMatterToDaysMatterVO(item);
            return daysMatterVO;
        }).collect(Collectors.toList());

        return daysMatterVOS;
    }

    /**
     *  修改倒数日事件
     * @param daysMatter    修改后的倒数日
     * @return              倒数日
     */
    @Override
    public DaysMatter updateDaysMatter(DaysMatter daysMatter) {
        // 获取用户的id
        Long userId = SecurityUtils.getUserId();
        //Long userId = 123456789L;

        daysMatter.setUserId(userId);

        // 获取目标时间
        LocalDate targetDay = daysMatter.getTargetDay();
        int daysBetween = getDaysNumByDay(targetDay, daysMatter.getRepeatType());

        if(daysBetween >= 0){
            // 目标时间是未来
            daysMatter.setMatterType(2);
            daysMatter.setDaysNum(daysBetween);

        }else {
            // 目标时间是过去
            daysMatter.setMatterType(1);
            daysMatter.setDaysNum(Math.abs(daysBetween));

        }

        this.updateById(daysMatter);
        return daysMatter;
    }


    /**
     *  删除倒数日事件
     * @param daysMatterId      倒数日的id
     */
    @Override
    public void deleteDaysMatter(Long daysMatterId) {
        // 查询构造器
        LambdaQueryWrapper<DaysMatter> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DaysMatter::getDaysMatterId, daysMatterId);

        this.remove(queryWrapper);
    }


    /**
     *  根据倒数日的id查询倒数日事件
     * @param daysMatterId  倒数日id
     * @return          倒数日事件
     */
    @Override
    public DaysMatter selectDaysMatter(Long daysMatterId) {

        return this.getById(daysMatterId);
    }


    /**
     * 倒数日的分页展示
     *
     * @param page         起始页
     * @param pageSize     终止页
     * @param userId       用户id
     * @return 倒数日集合
     */
    @Override
    public Page<DaysMatter> pageDaysMatter(Integer page, Integer pageSize, Long userId) {
        Page<DaysMatter> pageInfo = new Page<>(page, pageSize);

        // 查询构造器
        LambdaQueryWrapper<DaysMatter> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DaysMatter::getUserId, userId);

        // 添加条件
        // 按照状态降序，失效排在后面
        queryWrapper.orderByDesc(DaysMatter::getStatus);
        // 按照倒数日类型降序，未来的排在前面
        queryWrapper.orderByDesc(DaysMatter::getMatterType);
        // 按照距离目标事件的时间升序
        queryWrapper.orderByAsc(DaysMatter::getDaysNum);

        this.page(pageInfo, queryWrapper);

        return pageInfo;
    }

    @Override
    public void updateDaysMatterById(DaysMatter daysMatter, Long daysMatterId) {
        try {
            daysMatter.setDaysMatterId(daysMatterId);
            daysMatterMapper.updateById(daysMatter);

        }catch (Exception e){
            throw new BusinessException("更新倒数日失败");
        }
    }

    @Override
    public void deleteDaysMatterById(Long daysMatterId) {
        try {
            daysMatterMapper.deleteById(daysMatterId);
        }catch (Exception e){
            throw new BusinessException("删除倒数日失败");
        }
    }

    @Override
    public List<DaysMatter> getAllDaysMatterlist() {
        try {
            return daysMatterMapper.selectList(null);
        }catch (Exception e){
            throw new BusinessException("查询倒数日列表失败");
        }
    }



    public Integer getDaysNumByDay(LocalDate targetDay, Integer repeatType ){
        // 获取当前时间
        LocalDate currentDay = LocalDate.now();

        // 获取两个时间的间隔天数,并返回
        return Integer.parseInt(String.valueOf(ChronoUnit.DAYS.between(currentDay, targetDay)));
    }
}
